import { APlugin } from '../types/common.interface';
import {  Inject, Injectable, PluginInjectable } from '../decorators/inject';
import './col-width.plugin.less';
import './develop-help.plugin.less';
import { DrawHelper } from '../utils/draw-helper';
function getPixelRatio(context: any) {
    var backingStore = context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;
    // return 1;
    return (window.devicePixelRatio || 1) / backingStore;
}
const devtoolHtml = `
    <div class="dev-tools">
        <div class="lines">
        </div>
        <div class="tool-buttons">
            <div class="add tool-item">
                <a>+</a>
            </div>
            <div class="tool-item tool-btn toggle-size-helper">
                测宽高
            </div>
        </div>

        <div class="show"></div>
    </div>
`
const confHtml = `
<div class="line-conf">
<input class="color" type="color" default-value="red">
<div class="value-container">
  <input class="value x" type="number" />
  <span></span>
  <input class="value y" type="number"/>
</div>
<div class="remove">x</div>
</div>
`
const pxHelper = `
    <div class="px-top"></div>
    <div class="px-left"></div>
    <div class="px-right"></div>
    <div class="px-bottom"></div>
    <div class="px-size-info">0*0</div>
`;
function parseDom(arg: any): any {

    　　 var objE = document.createElement("div");
    
    　　 objE.innerHTML = arg;
    
    　　 return objE.childNodes;
    
};
@Injectable()
@PluginInjectable('DevelopHelpPlugin')
export class DevelopHelpPlugin  extends APlugin {
    protected ctx: CanvasRenderingContext2D;
    protected canvasEle: HTMLCanvasElement;
    protected devContainer: HTMLElement;
    protected confContainer: HTMLElement;
    protected confs: {color: string, x: number, y: number, id: number}[] = [];
    protected container: HTMLElement;
    protected pixelRatio = 1;
    protected get status() {
        let showStatus = localStorage.getItem('z-table-tools-show');
        if(showStatus === 'true') {
            return true;
        }
        return false;
    }
    protected set status(status: boolean) {
        localStorage.setItem('z-table-tools-show', status ? 'true':'false');
        this.devContainer.setAttribute('style', `display: ${status ? 'block':'none'}`);
        if(status) {
            this.canvasEle.style.opacity = '1';
            this.draw();
        } else {
            this.canvasEle.style.opacity = '0';
        }
    }
    constructor() {
        super();
    }
    public init() {
        setTimeout(() => {
            let container = document.querySelector('.z-canvas-container');
            // @ts-ignore
            this.container = container;
            let canvaseEle = document.createElement('canvas');
            canvaseEle.setAttribute('class', 'z-table-develop-helper');
            canvaseEle.setAttribute('style', ``);
            canvaseEle.setAttribute('style', `width: ${container.clientWidth}px; height: ${container.clientHeight}px`);
            let ratio = getPixelRatio(canvaseEle.getContext('2d'));
            this.pixelRatio = ratio;
            canvaseEle.height = container.clientHeight * ratio;
            canvaseEle.width = container.clientWidth * ratio;
            this.canvasEle = canvaseEle;
            this.ctx = this.canvasEle.getContext('2d');
            canvaseEle.style.opacity = this.status ? '1':'0'
            container.appendChild(canvaseEle);
            let pxHelperContainer = document.createElement('div');
            pxHelperContainer.setAttribute('class','px-helper dev-tools-hidden');
            pxHelperContainer.setAttribute('style', 'left: 20px;top: 20px;width: 40px;height:20px;')
            pxHelperContainer.innerHTML = pxHelper;
            document.querySelector('body').append(pxHelperContainer);
            document.querySelector('.toggle-size-helper').addEventListener('click', () => {
                let xpHelpEle = document.querySelector('.px-helper');
                if(xpHelpEle.classList.contains('dev-tools-hidden')) {
                    xpHelpEle.classList.remove('dev-tools-hidden');
                } else {
                    xpHelpEle.classList.add('dev-tools-hidden');
                }
            });
            let xpHelpEle = document.querySelector('.px-helper') as HTMLElement;
            const updateInfo = () => {
                let _ele = xpHelpEle.querySelector('.px-size-info') as HTMLElement;
                xpHelpEle.setAttribute('placeholder', `${xpHelpEle.style.width}*${xpHelpEle.style.height}`);
                _ele.innerText = `${xpHelpEle.style.width}*${xpHelpEle.style.height}`;
            }
            // @ts-ignore
            xpHelpEle.addEventListener('mousedown', (evt: MouseEvent) => {
                let clickX = evt.clientX;
                let clickY = evt.clientY;
                let left = Number(xpHelpEle.style.left.replace('px',''));
                let top = Number(xpHelpEle.style.top.replace('px',''));
                let moveFunc = (moveEvt: MouseEvent) => {
                    let currentX = moveEvt.clientX;
                    let currentY = moveEvt.clientY;
                    let currentLeft = left + currentX - clickX;
                    let currentTop = top + currentY - clickY;
                    xpHelpEle.style.top  = currentTop + 'px';
                    xpHelpEle.style.left = currentLeft + 'px';
                    updateInfo();
                };
                let mouseUp = (upEvt: MouseEvent) => {
                    document.removeEventListener('mousemove', moveFunc);
                    document.removeEventListener('mouseup', mouseUp);
                    updateInfo();
                }
                document.addEventListener('mousemove', moveFunc);
                document.addEventListener('mouseup', mouseUp);
            });
            // @ts-ignore
            xpHelpEle.querySelector('.px-top').addEventListener('mousedown', (downEvt: MouseEvent) => {
                downEvt.stopPropagation();
                downEvt.preventDefault();
                let clickY = downEvt.clientY;
                let top = Number(xpHelpEle.style.top.replace('px',''));
                let height = Number(xpHelpEle.style.height.replace('px',''));
                let moveFunc = (moveEvt: MouseEvent) => {
                    let currentY = moveEvt.clientY - clickY;
                    let currentTop = top + currentY;
                    xpHelpEle.style.top  = currentTop + 'px';
                    xpHelpEle.style.height = height - currentY + 'px';
                    updateInfo();
                };
                let mouseUp = (upEvt: MouseEvent) => {
                    document.removeEventListener('mousemove', moveFunc);
                    document.removeEventListener('mouseup', mouseUp);
                    updateInfo();
                }
                document.addEventListener('mousemove', moveFunc);
                document.addEventListener('mouseup', mouseUp);
            });
            // @ts-ignore
            xpHelpEle.querySelector('.px-left').addEventListener('mousedown', (downEvt: MouseEvent) => {
                downEvt.stopPropagation();
                downEvt.preventDefault();
                let clickX = downEvt.clientX;
                let left = Number(xpHelpEle.style.left.replace('px',''));
                let width = Number(xpHelpEle.style.width.replace('px',''));
                let moveFunc = (moveEvt: MouseEvent) => {
                    let currentX = moveEvt.clientX - clickX;
                    xpHelpEle.style.left  = left + currentX + 'px';
                    xpHelpEle.style.width = width - currentX + 'px';
                    updateInfo();
                };
                let mouseUp = (upEvt: MouseEvent) => {
                    document.removeEventListener('mousemove', moveFunc);
                    document.removeEventListener('mouseup', mouseUp);
                    updateInfo();
                }
                document.addEventListener('mousemove', moveFunc);
                document.addEventListener('mouseup', mouseUp);
            });
            // @ts-ignore
            xpHelpEle.querySelector('.px-right').addEventListener('mousedown', (downEvt: MouseEvent) => {
                downEvt.stopPropagation();
                downEvt.preventDefault();
                let clickX = downEvt.clientX;
                let width = Number(xpHelpEle.style.width.replace('px',''));
                let moveFunc = (moveEvt: MouseEvent) => {
                    let currentX = moveEvt.clientX - clickX;
                    xpHelpEle.style.width = width + currentX + 'px';
                    updateInfo();
                };
                let mouseUp = (upEvt: MouseEvent) => {
                    document.removeEventListener('mousemove', moveFunc);
                    document.removeEventListener('mouseup', mouseUp);
                    updateInfo();
                }
                document.addEventListener('mousemove', moveFunc);
                document.addEventListener('mouseup', mouseUp);
            });
            // @ts-ignore
            xpHelpEle.querySelector('.px-bottom').addEventListener('mousedown', (downEvt: MouseEvent) => {
                downEvt.stopPropagation();
                downEvt.preventDefault();
                let clickY = downEvt.clientY;
                let height = Number(xpHelpEle.style.height.replace('px',''));
                let moveFunc = (moveEvt: MouseEvent) => {
                    let currentY = moveEvt.clientY - clickY;
                    xpHelpEle.style.height = height + currentY + 'px';
                    updateInfo();
                };
                let mouseUp = (upEvt: MouseEvent) => {
                    document.removeEventListener('mousemove', moveFunc);
                    document.removeEventListener('mouseup', mouseUp);
                    updateInfo();
                }
                document.addEventListener('mousemove', moveFunc);
                document.addEventListener('mouseup', mouseUp);
            });
        });
        let devContainer: HTMLElement = parseDom(devtoolHtml)[1];
        if(localStorage.getItem('mini-tools') === '1') {
            devContainer.classList.add('tools-mini');
        }
        document.querySelector('body').append(devContainer);
        this.confContainer = devContainer.querySelector('.lines');
        devContainer.setAttribute('style', `display: ${this.status ? 'block':'none'}`);
        this.devContainer = devContainer;
        devContainer.querySelector('.add a').addEventListener('click', () => {
            this.addConf();
            localStorage.setItem('dev-conf', JSON.stringify(this.confs));
        });
        let conf = localStorage.getItem('dev-conf');
        if(conf) {
            let _values = JSON.parse(conf);
            for(let item of _values) {
                this.addConf(item.color, item.x, item.y);
            }
            setTimeout(() => {
                this.draw();
            },100);
        }
        document.addEventListener('keydown', e => {
            if(e.ctrlKey && (e.key === 't' || e.key === 'T')) {
                this.status = !this.status;
            }
        });
        document.querySelector('.show').addEventListener('click', () => {
            let ele = document.querySelector('.dev-tools');
            if(ele.classList.contains('tools-mini')) {
                ele.classList.remove('tools-mini');
                localStorage.setItem('mini-tools', '0')
            } else {
                ele.classList.add('tools-mini');
                localStorage.setItem('mini-tools', '1')
            }
        });
    }
    public addConf(color = '#000000', x = 0, y = 20) {
        let confEle = parseDom(confHtml)[1];
        this.confContainer.append(confEle);
        confEle.querySelector('.color').value = color;
        confEle.querySelector('.color').addEventListener('input', this.valueChange.bind(this));
        confEle.querySelector('.x').value = x;
        confEle.querySelector('.x').addEventListener('input', this.valueChange.bind(this));
        confEle.querySelector('.y').value = y;
        confEle.querySelector('.y').addEventListener('input', this.valueChange.bind(this));
        let obj: any = {};
        let id = new Date().getTime();
        Object.defineProperties(obj, {
            color: {
                get: () => {
                    return confEle.querySelector('.color').value
                }
            },
            x: {
                get: () => {
                    return Number(confEle.querySelector('.x').value);
                }
            },
            y: {
                get: () => {
                    return Number(confEle.querySelector('.y').value);
                },
            },
            id: {
                value: id
            }
        });
        confEle.querySelector('.remove').addEventListener('click', () => {
            let idx = this.confs.findIndex(item => item.id === id);
            this.confs.splice(idx, 1);
            confEle.remove();
            this.valueChange();
        });
        this.confs.push(obj);
        this.saveValue();
    }
    public destroy() {

    }
    protected draw() {
        let endX = this.container.clientWidth * this.pixelRatio;
        let endY = this.container.clientHeight * this.pixelRatio;
        this.ctx.clearRect(0,0, endX, endY);
        for(let item of this.confs) {
            if(item.x === 0 && item.y === 0) {
                continue;
            }
            let drawLine = DrawHelper.line(this.ctx)({width: 1, type: 'solid', color: item.color});
            if(item.x === 0) {
                drawLine({x: 0, y: item.y}, {x: endX, y: item.y});
            }
            if(item.y === 0) {
                drawLine({x: item.x, y: 0}, {x: item.x, y: endY});
            }
        }
    }
    protected saveValue() {
        let values: any[] = [];
        for(let item of this.confs) {
            values.push({color: item.color, x: item.x, y: item.y});
        } 
        localStorage.setItem('dev-conf', JSON.stringify(values));
    }
    public valueChange() {
        this.saveValue();
        this.draw();
    }
}